package fserv.fileshare;

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
import fserv.control.ClientController;

/**
 * File share module: File Getter.
 * 
 * Launches a thread, gets a file shared by a remote peer
 * and saves it to a local file.
 * 
 * @author Arthur Bit-Monnot <abit@etud.insa-toulouse.fr>
 * @author Julien Marchand <jmarchan@etud.insa-toulouse.fr>
 */
public class FileGetter extends Thread {

    /**
     * Reference to the Chat Controller.
     */
    private ClientController ctrl;
    
    /**
     * Local file to store the shared file.
     */
    private File file;
    
    /**
     * IP address of the remote peer that shares the file.
     */
    private InetAddress addr;
    
    /**
     * TCP port on which the file is shared.
     */
    private int port;
    
    /**
     * Size of the shared file.
     */
    private long size;
    
    /**
     * Constructor of a FileGetter.
     * 
     * @param ctrl the reference to the ClientController
     * @param file the local file to store the shared file
     * @param addr the InetAddress of the remote peer who shares the file
     * @param port the TCP port on which the file is shared
     * @param size the size of the shared file
     */
    public FileGetter(ClientController ctrl, File file, InetAddress addr, int port, long size) {
        this.ctrl = ctrl;
        this.file = file;
        this.addr = addr;
        this.port = port;
        this.size = size;
    }
    
    /**
     * Connects to the remote peer, gets the shared file and stores it to the
     * specified local file.
     * Displays a progress bar.
     */
    @Override
    public void run() {
        Logger.getLogger(FileGetter.class.getName()).log(Level.INFO, "Starting.");
        
        ctrl.fileShareDownloadStarted(file, addr);
        
        BufferedOutputStream bos = null;
        Socket sock = null;
        try {
            sock = new Socket(addr, port);
            
            InputStream is = new BufferedInputStream(sock.getInputStream());
            
            bos = new BufferedOutputStream(new FileOutputStream(file));
            byte[] buffer = new byte[sock.getReceiveBufferSize()];
            int read;
            while ((read = is.read(buffer)) != -1) {
                bos.write(buffer, 0, read);
            }
            
            ctrl.fileShareDownloadFinished(file, addr);
        } catch (IOException ex) {
            Logger.getLogger(FileGetter.class.getName()).log(Level.SEVERE, null, ex);
            ctrl.fileShareDownloadFailed(file, addr);
        } finally {
            try {
                if (bos != null) {
                    bos.close();
                }
            } catch (IOException ex) {
                Logger.getLogger(FileGetter.class.getName()).log(Level.SEVERE, null, ex);
            }
            try {
                if (sock != null) {
                    sock.close();
                }
            } catch (IOException ex) {
                Logger.getLogger(FileGetter.class.getName()).log(Level.SEVERE, null, ex);
            }        
        }
        
        Logger.getLogger(FileGetter.class.getName()).log(Level.INFO, "Exiting.");
    }
}
